/** 对象权重组 */
export default class WeightGroup<T> {

    private _weightMap = new Map<T, number>()
    private _spanArr: { max: number, obj: T }[]
    private _total = 0

    /** 请使用create */
    private constructor() { }

    /** 创建对象权重组 */
    static create<T>(weightArr: { obj: T, weight: number }[]) {

        let wg = new WeightGroup<T>()
        weightArr.forEach(w => {
            wg._weightMap.set(w.obj, w.weight)
            wg._total += w.weight
        })
        wg.update()

        return wg
    }

    setOne(obj: T, weight: number, update = true) {
        let w = this._weightMap.get(obj)
        this._weightMap.set(obj, weight)
        this._total += w != undefined ? weight - w : weight
        update && this.update()
    }

    delOne(obj: T, update = true) {
        let w = this._weightMap.get(obj)
        if (w != undefined) {
            this._weightMap.delete(obj)
            this._total -= w
            update && this.update()
        }
    }

    /** 从权重组中随机一个对象 */
    getOne() {
        let r = Math.random() * this._total
        let i = this._spanArr.length
        while (i--) {
            let span = this._spanArr[i]
            if (r < span.max) {
                return span.obj
            }
        }
    }

    /** 更新权重 */
    update() {
        let temp = this._total
        this._spanArr = []
        this._weightMap.forEach((w, obj) => {
            this._spanArr.push({ obj, max: temp })
            temp -= w
        })
    }
}